package com.example.pc.videodemo

import android.Manifest
import android.annotation.SuppressLint
import android.app.role.RoleManager
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.media.AudioFormat
import android.media.AudioManager
import android.media.AudioRecord
import android.media.MediaRecorder
import android.net.ConnectivityManager
import android.net.Uri
import android.net.wifi.WifiManager
import android.os.Build
import android.os.Bundle
import android.os.PowerManager
import android.provider.CallLog
import android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
import android.telecom.TelecomManager
import android.telephony.PhoneStateListener
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.text.InputType
import android.text.TextUtils
import android.util.Base64
import android.util.Log
import android.view.KeyEvent
import android.view.KeyEvent.KEYCODE_BACK
import android.view.View
import android.view.View.*
import android.widget.SeekBar
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.example.myapplication.CrashHandler
import com.example.myapplication.rabbitmq.OnReceivedDataListener
import com.example.pc.videodemo.Util.UpdateListener
import com.example.pc.videodemo.bean.BaseResponse
import com.example.pc.videodemo.bean.IdModel
import com.example.pc.videodemo.emq.MqttConfig
import com.example.pc.videodemo.emq.MqttManager
import com.example.pc.videodemo.emq.model.EmqConstant
import com.example.pc.videodemo.emq.model.MqttMassgeSubscribBase
import com.example.pc.videodemo.http.ApiService
import com.example.pc.videodemo.http.RetrofitFactory
import com.tbruyelle.rxpermissions2.RxPermissions
import io.agora.rtc2.*
import io.agora.rtc2.internal.AudioRecordingConfiguration
import io.agora.rtc2.internal.EncryptionConfig
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.activity_home.btn_call
import kotlinx.android.synthetic.main.activity_home.btn_del
import kotlinx.android.synthetic.main.activity_home.btn_login
import kotlinx.android.synthetic.main.activity_home.btn_quit
import kotlinx.android.synthetic.main.activity_home.btn_refresh_net
import kotlinx.android.synthetic.main.activity_home.et_name
import kotlinx.android.synthetic.main.activity_home.et_net_address
import kotlinx.android.synthetic.main.activity_home.et_pass
import kotlinx.android.synthetic.main.activity_home.img_show_hide
import kotlinx.android.synthetic.main.activity_home.layout_login
import kotlinx.android.synthetic.main.activity_home.layout_num
import kotlinx.android.synthetic.main.activity_home.ll_loading
import kotlinx.android.synthetic.main.activity_home.sb
import kotlinx.android.synthetic.main.activity_home.tv1
import kotlinx.android.synthetic.main.activity_home.tv2
import kotlinx.android.synthetic.main.activity_home.tv_left
import kotlinx.android.synthetic.main.activity_home.tv_loading_info
import kotlinx.android.synthetic.main.activity_home.tv_local
import kotlinx.android.synthetic.main.activity_home.tv_logo
import kotlinx.android.synthetic.main.activity_home.tv_name
import kotlinx.android.synthetic.main.activity_home.tv_phone_num
import kotlinx.android.synthetic.main.activity_home.tv_right
import kotlinx.android.synthetic.main.activity_home.tv_show_local
import kotlinx.android.synthetic.main.activity_home.tv_version
import kotlinx.android.synthetic.main.activity_home2.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import org.json.JSONException
import org.json.JSONObject
import retrofit2.Call
import retrofit2.Response
import java.io.*
import java.lang.reflect.Field
import java.net.*
import java.util.*
import javax.security.auth.callback.Callback
import kotlin.concurrent.thread
import kotlin.math.abs


class MainActivity : AppCompatActivity(), OnReceivedDataListener {

    private var enableAudioRecording: Boolean = false
    private var joined: Boolean = false
    private var disposable: Disposable? = null
    private var isGranted = false
    private var isRecording = false
    private var mqttManager: MqttManager? = null
    private var kind: Int = 0
    private var conState = 0
    private var simState = 0
    private var voiState = 0
    private var myUid = 0
    private var ouCallNum: String = ""
    private var accessToken: String? = null
    private var remoteIp = "192.168.31.254"
    var encryptionKdfSaltBase64: String? = null
    private var volume = 50
    var encryptionSecret: String? = null
    private var mRtcEventHandler: IRtcEngineEventHandler = object : IRtcEngineEventHandler() {
        /**Reports a warning during SDK runtime.
         * Warning code: https://docs.agora.io/en/Voice/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_engine_event_handler_1_1_warn_code.html */
        @Deprecated("Deprecated in Java")
        override fun onWarning(warn: Int) {
            Log.w(TAG, String.format("onWarning code %d message %s", warn, RtcEngine.getErrorDescription(warn)))
        }

        /**Occurs when a user leaves the channel.
         * @param stats With this callback, the application retrieves the channel information,
         * such as the call duration and statistics.
         */
        override fun onLeaveChannel(stats: RtcStats) {
            super.onLeaveChannel(stats)
            joined = false
            Log.i(TAG, java.lang.String.format("local user %d leaveChannel!", myUid))

        }

        override fun onAudioRouteChanged(routing: Int) {
            super.onAudioRouteChanged(routing)
            Log.i(TAG, "routing $routing")
            engine?.setEnableSpeakerphone(false)

        }

        override fun onLocalAudioStateChanged(state: Int, error: Int) {
            super.onLocalAudioStateChanged(state, error)
//            if (state == 0) {
//                toast("又静音了")
//            }
        }

        /**Occurs when the local user joins a specified channel.
         * The channel name assignment is based on channelName specified in the joinChannel method.
         * If the uid is not specified when joinChannel is called, the server automatically assigns a uid.
         * @param channel Channel name
         * @param uid User ID
         * @param elapsed Time elapsed (ms) from the user calling joinChannel until this callback is triggered
         */
        override fun onJoinChannelSuccess(channel: String, uid: Int, elapsed: Int) {
            Log.i(TAG, String.format("onJoinChannelSuccess channel %s uid %d", channel, uid))
            myUid = uid
            joined = true
//            engine?.setEnableSpeakerphone(false)

        }

        override fun onConnectionStateChanged(state: Int, reason: Int) {
            Log.i(TAG, "onConnectionStateChanged state $state reason $reason")
            val stringBuffer = StringBuffer()
            when (state) {
                1 -> stringBuffer.append("网络连接断开\n")
                2 -> stringBuffer.append("建立网络连接中\n")
                3 -> stringBuffer.append("网络已连接\n")
                4 -> stringBuffer.append("重新建立网络连接中\n")
                5 -> {
                    stringBuffer.append("网络连接失败\n")
                    joinChannel()
                }
            }
            when (reason) {
                0 -> stringBuffer.append("建立网络连接中")
                1 -> stringBuffer.append("成功加入频道")
                2 -> stringBuffer.append("网络连接中断")
                3 -> stringBuffer.append("网络连接被服务器禁止")
                4 -> stringBuffer.append("加入频道失败")
                5 -> stringBuffer.append("离开频道")
                6 -> stringBuffer.append("不是有效的 APP ID。")
                7 -> stringBuffer.append("不是有效的频道名。")
                8 -> stringBuffer.append("生成的 Token 无效")
                9 -> stringBuffer.append("当前使用的 Token 过期")
                10 -> stringBuffer.append("此用户被服务器禁止")
                11 -> stringBuffer.append("由于设置了代理服务器，SDK 尝试重连")
                12 -> stringBuffer.append("更新 Token 引起网络连接状态改变")
                13 -> stringBuffer.append("客户端 IP 地址变更")
                14 -> stringBuffer.append("SDK 和服务器连接保活超时，进入自动重连状态")
                15 -> stringBuffer.append("重新加入频道成功")
                16 -> stringBuffer.append("和服务器失去连接 ")
                17 -> stringBuffer.append("连接状态变化由回声测试引起")
                18 -> stringBuffer.append("本地 IP 地址被用户更改")
                19 -> stringBuffer.append("使用相同的 UID 从不同的设备加入同一频道")
                20 -> stringBuffer.append("使用相同的 UID 从不同的设备加入同一频道")


            }
            toast(stringBuffer.toString())
        }

        /**Since v2.9.0.
         * This callback indicates the state change of the remote audio stream.
         * PS: This callback does not work properly when the number of users (in the Communication profile) or
         * broadcasters (in the Live-broadcast profile) in the channel exceeds 17.
         * @param uid ID of the user whose audio state changes.
         * @param state State of the remote audio
         * REMOTE_AUDIO_STATE_STOPPED(0): The remote audio is in the default state, probably due
         * to REMOTE_AUDIO_REASON_LOCAL_MUTED(3), REMOTE_AUDIO_REASON_REMOTE_MUTED(5),
         * or REMOTE_AUDIO_REASON_REMOTE_OFFLINE(7).
         * REMOTE_AUDIO_STATE_STARTING(1): The first remote audio packet is received.
         * REMOTE_AUDIO_STATE_DECODING(2): The remote audio stream is decoded and plays normally,
         * probably due to REMOTE_AUDIO_REASON_NETWORK_RECOVERY(2),
         * REMOTE_AUDIO_REASON_LOCAL_UNMUTED(4) or REMOTE_AUDIO_REASON_REMOTE_UNMUTED(6).
         * REMOTE_AUDIO_STATE_FROZEN(3): The remote audio is frozen, probably due to
         * REMOTE_AUDIO_REASON_NETWORK_CONGESTION(1).
         * REMOTE_AUDIO_STATE_FAILED(4): The remote audio fails to start, probably due to
         * REMOTE_AUDIO_REASON_INTERNAL(0).
         * @param reason The reason of the remote audio state change.
         * REMOTE_AUDIO_REASON_INTERNAL(0): Internal reasons.
         * REMOTE_AUDIO_REASON_NETWORK_CONGESTION(1): Network congestion.
         * REMOTE_AUDIO_REASON_NETWORK_RECOVERY(2): Network recovery.
         * REMOTE_AUDIO_REASON_LOCAL_MUTED(3): The local user stops receiving the remote audio
         * stream or disables the audio module.
         * REMOTE_AUDIO_REASON_LOCAL_UNMUTED(4): The local user resumes receiving the remote audio
         * stream or enables the audio module.
         * REMOTE_AUDIO_REASON_REMOTE_MUTED(5): The remote user stops sending the audio stream or
         * disables the audio module.
         * REMOTE_AUDIO_REASON_REMOTE_UNMUTED(6): The remote user resumes sending the audio stream
         * or enables the audio module.
         * REMOTE_AUDIO_REASON_REMOTE_OFFLINE(7): The remote user leaves the channel.
         * @param elapsed Time elapsed (ms) from the local user calling the joinChannel method
         * until the SDK triggers this callback.
         */
        override fun onRemoteAudioStateChanged(uid: Int, state: Int, reason: Int, elapsed: Int) {
            super.onRemoteAudioStateChanged(uid, state, reason, elapsed)
            Log.i(TAG, "onRemoteAudioStateChanged->$uid, state->$state, reason->$reason")
        }

        /**Occurs when a remote user (Communication)/host (Live Broadcast) joins the channel.
         * @param uid ID of the user whose audio state changes.
         * @param elapsed Time delay (ms) from the local user calling joinChannel/setClientRole
         * until this callback is triggered.
         */
        override fun onUserJoined(uid: Int, elapsed: Int) {
            super.onUserJoined(uid, elapsed)
            Log.i(TAG, "onUserJoined->$uid")

        }

        /**Occurs when a remote user (Communication)/host (Live Broadcast) leaves the channel.
         * @param uid ID of the user whose audio state changes.
         * @param reason Reason why the user goes offline:
         * USER_OFFLINE_QUIT(0): The user left the current channel.
         * USER_OFFLINE_DROPPED(1): The SDK timed out and the user dropped offline because no data
         * packet was received within a certain period of time. If a user quits the
         * call and the message is not passed to the SDK (due to an unreliable channel),
         * the SDK assumes the user dropped offline.
         * USER_OFFLINE_BECOME_AUDIENCE(2): (Live broadcast only.) The client role switched from
         * the host to the audience.
         */
        override fun onUserOffline(uid: Int, reason: Int) {
            Log.i(TAG, String.format("user %d offline! reason:%d", uid, reason))
//            engine?.leaveChannel()
        }

        override fun onActiveSpeaker(uid: Int) {
            super.onActiveSpeaker(uid)
            Log.i(TAG, String.format("onActiveSpeaker:%d", uid))
        }
    }
    private var channelName = "Test"
    private var engine: RtcEngine? = null
    private val service by lazy {
//        if (!TextUtils.isEmpty(Util.getIp(this@MainActivity)))
        RetrofitFactory.newInstance.create(ApiService::class.java)
    }

    private var dialog: AlertDialog? = null

    private var loadingDialog: LoadingDialog? = null

    companion object {

        private const val TAG = "MainActivity"

    }

    var b = true
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home)

        when (packageName) {
            "com.example.pc.videodemo.cons" -> {
                setContentView(R.layout.activity_home)
                kind = 0
                MqttConfig.PUBLICTOPIC = "server/con"
                tv_logo.text = "控制端"

            }
            "com.example.pc.videodemo.voi" -> {
                setContentView(R.layout.activity_home2)
                kind = 2
                MqttConfig.PUBLICTOPIC = "server/voi"
                tv_logo.text = "语音端"
            }
            "com.example.pc.videodemo.sim" -> {
                setContentView(R.layout.activity_home2)
                kind = 1
                MqttConfig.PUBLICTOPIC = "server/sim"
                tv_logo.text = "插卡端"
                showCardCallIng(false)
                /* val intent = Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
                 intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, packageName)
                 startActivity(intent)*/
            }
        }
        Util.getUpdate(kind, object : UpdateListener {
            override fun onNew(url: String?) {
                runOnUiThread {
                    AlertDialog.Builder(this@MainActivity).setNegativeButton("前往下载更新", object : DialogInterface.OnClickListener {
                        override fun onClick(dialog: DialogInterface?, which: Int) {
                            val intent = Intent(Intent.ACTION_VIEW)
                            intent.data = Uri.parse(url)
                            startActivity(intent)
                            finish()
                        }
                    }).setMessage("有新版本").setCancelable(false).create().show()
                }
            }
        })

//        kind = resources.getInteger(R.integer.app_kind)
        val powerManager: PowerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
        if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
            val intent = Intent()

            intent.action = ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
            intent.data = Uri.parse("package:$packageName")
            startActivity(intent)

        }
/*tv_name.setOnClickListener(object :OnClickListener{
    override fun onClick(v: View?) {


        b= !b
        if (b){
            engine?.adjustRecordingSignalVolume(100)
        }else            engine?.adjustRecordingSignalVolume(0)

    }
})*/
        requestPermission()
        MyContext.setIp(Util.getIp(this))
        et_net_address.setText(Util.getIp(this))
        if (MyContext.getIp() == null) {
            toast("未配置服务器地址")
            btn_login.isEnabled = false
        }
        MqttConfig.HOST = "tcp://${Util.getIp(this)}:1883"

        layout_login.visibility = VISIBLE
        /*  if (mScreenListener == null) {
              mScreenListener = ScreenReceiverUtil(this);
              mScreenManager = ScreenManager.getScreenManagerInstance(this);
              mScreenListener?.setScreenReceiverListener(mScreenListenerer);
          }*/

        tv_version.text = "v.${BuildConfig.VERSION_NAME}"
//        startService(Intent(this, MqttMessageService::class.java))
        if (kind != 0) {
            et_pass.visibility = GONE
            img_show_hide.visibility = GONE
            tv_show_con.visibility = VISIBLE
            tv_con.visibility = VISIBLE
            layout_num.visibility = INVISIBLE
            tv_right.visibility = GONE
            tv_left.visibility = GONE
            tv1.visibility = GONE
            tv2.visibility = GONE
            img_sim.visibility = GONE
            img_voi.visibility = GONE
            img_logo.visibility = VISIBLE
            if (kind == 1) {
                img_logo.setImageResource(R.drawable.icon_sim)
            } else {
                img_logo.setImageResource(R.drawable.icon_voi)

            }
        }
        if (kind != 1) {
            sb.visibility = VISIBLE

            sb.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
                override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                    volume = progress
                    engine?.adjustPlaybackSignalVolume(volume)
                }

                override fun onStartTrackingTouch(seekBar: SeekBar?) {
                }

                override fun onStopTrackingTouch(seekBar: SeekBar?) {
                }
            })
        }
        changeState()

        val netWorkReceiver = NetworkReceiver()
        val filter = IntentFilter()
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION)
        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION)
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
        registerReceiver(netWorkReceiver, filter)

        btn_refresh_net.setOnClickListener {
            if (!isGranted) {
                requestPermission()
                return@setOnClickListener
            }
            if (et_net_address.text != null) {
                Util.saveAddress(this, et_net_address.text.toString())
                MyContext.setIp(et_net_address.text.toString())
//                btn_login.isEnabled = true
                toast("设置成功，请重启程序")
            }
        }
        btn_login.setOnClickListener {
            if (MyContext.getIp().isEmpty()) {
                toast("服务器地址为空")
                return@setOnClickListener
            }
//            val li=1/0
            ll_loading.visibility = VISIBLE
            when (kind) {
                0 -> service.controlLogin(IdModel(Util.getIp(this@MainActivity),
                        et_name.text.toString(), et_pass.text.toString())).enqueue(object : Callback, retrofit2.Callback<BaseResponse> {
                    override fun onFailure(call: Call<BaseResponse>, t: Throwable) {
                        toast("请求出错")
                        ll_loading.visibility = GONE

                    }

                    override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
                        if (response.body()?.code == 0 && response.body()?.msg.equals("success")) {
                            response.body()?.controlSideCode?.let { it1 -> initEmq(it1) }
                            tv_name.text = "已登录:" + et_name.text.toString()
                            layout_login.visibility = GONE
                            btn_quit.visibility = VISIBLE
                            layout_num.visibility = VISIBLE

                            channelName = et_name.text.toString()
                            if (response.body()?.sim?.toString()?.isNotEmpty() == true) {
                                simState = if (response.body()?.sim?.toString()?.contains(EmqConstant.serverToAndroidEnum.occupy.code)!!)
                                    2
                                else 1
                            }
                            if (response.body()?.voi?.toString()?.isNotEmpty() == true) {
                                voiState = 1
                            }
                            changeState()

                            return
                        }
                        response.body()?.msg?.let { it1 -> toast(it1) }
                        ll_loading.visibility = GONE
                    }

                })
                1 -> service.simCardLogin(IdModel(Util.getIp(this@MainActivity),
                        et_name.text.toString(), et_pass.text.toString())).enqueue(object : Callback, retrofit2.Callback<BaseResponse> {
                    override fun onFailure(call: Call<BaseResponse>, t: Throwable) {
                        toast("请求出错")
                        ll_loading.visibility = GONE
                    }

                    override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
                        if (response.body()?.code == 0 && response.body()?.msg.equals("success")) {
                            response.body()?.simCardSideCode?.let { it1 -> initEmq(it1) }
                            tv_name.text = "已登录:" + et_name.text.toString()
                            layout_login.visibility = GONE
                            btn_quit.visibility = VISIBLE
                            if (response.body()?.con?.toString()?.isNotEmpty() == true) {
                                conState = 1
                            }
                            changeState()
                            return
                        }
                        response.body()?.msg?.let { it1 -> toast(it1) }

                        ll_loading.visibility = GONE
                    }
                })
                else -> service.voiceLogin(IdModel(Util.getIp(this@MainActivity), et_name.text.toString(), et_pass.text.toString())).enqueue(object : Callback, retrofit2.Callback<BaseResponse> {
                    override fun onFailure(call: Call<BaseResponse>, t: Throwable) {
                        toast("请求出错")
                        ll_loading.visibility = GONE
                    }

                    override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
                        if (response.body()?.code == 0 && response.body()?.msg.equals("success")) {
                            response.body()?.voiceSideCode?.let { it1 -> initEmq(it1) }
                            tv_name.text = "已登录:" + et_name.text.toString()
                            channelName = et_name.text.toString()
                            layout_login.visibility = GONE
                            btn_quit.visibility = VISIBLE
                            //                        initWebSocket()
                            if (response.body()?.con?.toString()?.isNotEmpty() == true) {
                                conState = 1
                            }

                            changeState()
                            return
                        }
                        response.body()?.msg?.let { it1 -> toast(it1) }

                        ll_loading.visibility = GONE
                    }
                })
            }

        }
        btn_call.setOnClickListener {
            if (tv_phone_num.text.toString().isEmpty())
                return@setOnClickListener
            ouCallNum = tv_phone_num.text.toString()
            mqttManager?.call(ouCallNum)
            stringBuffer = StringBuffer()
            tv_phone_num.text = ""
            btn_del.visibility = GONE
            if (loadingDialog == null) {
                createLoadingDialog()
            } else {
                loadingDialog?.setPhone(ouCallNum)
            }
            loadingDialog?.setOutCall(true)
            loadingDialog?.show()
            thread {
                var i = 0
                var isCount = true
                while (isCount) {
                    if (i++ < 10) {
                        if (loadingDialog?.isShow() == true) {
                            Thread.sleep(1000)
                        } else {
                            isCount = false
                        }
                    } else {
                        if (loadingDialog?.isShow() == true) {

                            if (simState == 1) {
                                runOnUiThread {
                                    loadingDialog?.onTimeOut()
                                    stringBuffer = StringBuffer()
                                    tv_phone_num.text = ""
                                    btn_del.visibility = GONE
                                }
                                Thread.sleep(1000)
                                runOnUiThread {
                                    loadingDialog?.hide()
                                    toast("B端无响应")
                                }
                            }
                        }
                        isCount = false
                    }
                }


            }
        }

//
    }

    private fun createLoadingDialog() {
        loadingDialog = LoadingDialog(this, ouCallNum, onClickListener = OnClickListener {
            toast("控制端通话挂断 ")
            loadingDialog?.num?.let { mqttManager?.hangup(it) }
            stringBuffer = StringBuffer()
            tv_phone_num.text = ""
            btn_del.visibility = GONE
            loadingDialog?.hide()
        }, onAnswerClickListener = OnClickListener {
            mqttManager?.answer(loadingDialog?.num)
            loadingDialog?.onTalking()
        }, onMicChangeListener = object : LoadingDialog.OnMicChangeListener {
            override fun onMicChange(boolean: Boolean) {
                if (loadingDialog?.isShow() == false) {
                    return
                }
                if (engine == null) {
                    toast("语音未就绪")
                    return

                } else {
                }

                if (boolean) {
                    toast("语音已静音,点击麦克风按钮恢复")
                    //                engine?.enableLocalAudio(boolean)
                    engine?.adjustRecordingSignalVolume(0)
                } else {
                    engine?.adjustRecordingSignalVolume(100)

                }

            }

        })
    }

    private fun getTokenAndKey() {
        service.getToken(IdModel(channelName = channelName)).enqueue(object : Callback, retrofit2.Callback<BaseResponse> {
            override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
                if (response.body()?.code == 0 && response.body()?.msg.equals("success")) {
                    accessToken = response.body()?.token
                    /* service.getSecretKey().enqueue(object : Callback, retrofit2.Callback<BaseResponse> {
                         override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
                             if (response.body()?.code == 0 && response.body()?.msg.equals("success")) {
                                 encryptionSecret = response.body()?.secretKey
                                 encryptionKdfSaltBase64 = response.body()?.salt*/
                    initializeChannel()
                    /*  } else {
                          response.body()?.msg?.let {
                              toast(it)
                          }
                          ll_loading.visibility = GONE
                      }

                  }

                  override fun onFailure(call: Call<BaseResponse>, t: Throwable) {
                      toast("请求出错")
                      ll_loading.visibility = GONE
                  }
              })*/
                } else {
                    response.body()?.msg?.let { toast(it) }
                    ll_loading.visibility = GONE
                }
            }

            override fun onFailure(call: Call<BaseResponse>, t: Throwable) {
                toast("请求出错")
                ll_loading.visibility = GONE

            }

        })
    }

    private fun enableEncryption(): Boolean {
        if (engine == null) return false

        if (encryptionKdfSaltBase64 == null || encryptionSecret == null) return false
//        val encryptionKdfSalt: ByteArray = Base64.getDecoder().decode(encryptionKdfSaltBase64)
        val encryptionKdfSalt: ByteArray = Base64.decode(encryptionKdfSaltBase64, Base64.DEFAULT)
        val config = EncryptionConfig()
        config.encryptionMode = EncryptionConfig.EncryptionMode.AES_128_GCM2
        config.encryptionKey = encryptionSecret
        System.arraycopy(encryptionKdfSalt, 0, config.encryptionKdfSalt, 0, config.encryptionKdfSalt.size)
        val result = engine?.enableEncryption(true, config)
        return result == 0
    }

    private fun requestPermission() {
        disposable = RxPermissions(this)
                .request(Manifest.permission.RECORD_AUDIO, Manifest.permission.PROCESS_OUTGOING_CALLS,
                        Manifest.permission.BLUETOOTH, Manifest.permission.MODIFY_AUDIO_SETTINGS,
                        Manifest.permission.READ_SMS,

                        Manifest.permission.READ_CALL_LOG, Manifest.permission.WRITE_CALL_LOG,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CALL_PHONE, Manifest.permission.READ_PHONE_STATE)
                .subscribe { granted ->
                    if (!granted) {
                        toast("拒绝权限申请, 录音功能无法使用")
                        btn_login.isEnabled = false
                        return@subscribe
                    }
                    if (kind == 1) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                            val roleManager: RoleManager =
                                    getSystemService(Context.ROLE_SERVICE) as RoleManager

//                if (roleManager.isRoleAvailable(RoleManager.ROLE_DIALER)) {
//toast("已设置默认通话软件")
//                }else{
                            val intent: Intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER)
                            startActivityForResult(intent, 666)
//                }
                        } else {
                            val intent = Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
                            intent.action = TelecomManager.ACTION_CHANGE_DEFAULT_DIALER
                            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                            intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, packageName)
                            startActivityForResult(intent, 555)
                        }
                    }
                    isGranted = true

                }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            disposable = RxPermissions(this)
                    .request(Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_ADVERTISE,
                            Manifest.permission.BLUETOOTH_SCAN)
                    .subscribe { granted ->
                        if (!granted) {
                            toast("拒绝权限申请, 蓝牙模块不可用")
                            btn_login.isEnabled = false
                            return@subscribe
                        }

                        isGranted = true

                    }
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            disposable = RxPermissions(this)
                    .request(Manifest.permission.READ_PHONE_NUMBERS,
                            Manifest.permission.ANSWER_PHONE_CALLS)
                    .subscribe { granted ->
                        if (!granted) {
                            toast("拒绝权限申请, 接听电话不可用")
                            btn_login.isEnabled = false
                            return@subscribe
                        }

                        isGranted = true

                    }
        }
    }

    private fun initEmq(s: String) {
        mqttManager = MqttManager.instance
        mqttManager?.setSn(s)
        mqttManager?.setOnReceivedDataListener(this)
        mqttManager?.start()
        thread {

            val file = Util.upload(this, s, et_name.text.toString())

            if (file != null) {
                val requestBody: RequestBody = file.asRequestBody("multipart/form-data".toMediaTypeOrNull())
                val createFormData: MultipartBody.Part = MultipartBody.Part.createFormData("file", file.name, requestBody)
                service.upload(createFormData).enqueue(object : Callback, retrofit2.Callback<BaseResponse> {
                    override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
                        Log.i(TAG, "onResponse: $response")
                        if (response.body()?.code == 0 && response.body()?.msg.equals("success")) {
                            file.delete()
                            val logList = File(externalCacheDir.toString() + "/log")//源文件或者目录
                            if (logList.exists() && logList.isDirectory) {
                                val files = logList.listFiles()
                                for (file1 in files) {
                                    if (file1.isFile) {
                                        file1.delete()
                                    }

                                }
                                logList.delete()
                            }
                        } else {
                            file.delete()
                        }
                    }

                    override fun onFailure(call: Call<BaseResponse>, t: Throwable) {
                        Log.i(TAG, "onResponse: $t")
                        file.delete()
                    }
                })
            }
        }

    }


    private fun initializeChannel() {
        try {
            val config = RtcEngineConfig()
            /**
             * The context of Android Activity
             */
            config.mContext = applicationContext
            /**
             * The App ID issued to you by Agora. See [ How to get the App ID](https://docs.agora.io/en/Agora%20Platform/token#get-an-app-id)
             */
            config.mAppId = getString(R.string.agora_app_id)
            /** Sets the channel profile of the Agora RtcEngine.
             * CHANNEL_PROFILE_COMMUNICATION(0): (Default) The Communication profile.
             * Use this profile in one-on-one calls or group calls, where all users can talk freely.
             * CHANNEL_PROFILE_LIVE_BROADCASTING(1): The Live-Broadcast profile. Users in a live-broadcast
             * channel have a role as either broadcaster or audience. A broadcaster can both send and receive streams;
             * an audience can only receive streams. */
            config.mChannelProfile = Constants.CHANNEL_PROFILE_COMMUNICATION
            /**
             * IRtcEngineEventHandler is an abstract class providing default implementation.
             * The SDK uses this class to report to the app on SDK runtime events.
             */
            config.mEventHandler = mRtcEventHandler

            config.mAudioScenario = Constants.AudioScenario.getValue(Constants.AudioScenario.DEFAULT)
            engine = RtcEngine.create(config)
            engine?.enableSoundPositionIndication(false)
//            engine?.setDefaultAudioRoutetoSpeakerphone(true)
            engine?.setAudioProfile(4)//音质1-4
            engine?.setAudioScenario(3)
            engine?.adjustPlaybackSignalVolume(volume)
//            engine?.setEarMonitoringAudioFrameParameters(44100, 2, 0, 1024)
            engine?.setEnableSpeakerphone(false)
            enableEncryption()
            if (enableAudioRecording) {
                val audioRecordingConfiguration = AudioRecordingConfiguration()
                audioRecordingConfiguration.filePath = "audioDump"
                audioRecordingConfiguration.codec = false
                audioRecordingConfiguration.sampleRate = 44100
                /**
                 * The audio file record type.
                 * AUDIO_FILE_RECORDING_MIC = 1,
                 * AUDIO_FILE_RECORDING_PLAYBACK = 2,
                 * AUDIO_FILE_RECORDING_MIXED = 3,
                 */
                audioRecordingConfiguration.fileRecordOption = 1
                /**
                 * The audio recording quality type.
                 * AUDIO_RECORDING_QUALITY_LOW = 0,
                 * AUDIO_RECORDING_QUALITY_MEDIUM = 1,
                 * AUDIO_RECORDING_QUALITY_HIGH = 2,
                 */
                audioRecordingConfiguration.quality = 2
                engine?.startAudioRecording(audioRecordingConfiguration)
            }

            if ((kind == 0 && voiState == 1) || (kind == 2 && conState == 1))
                joinChannel()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            onBackPressed()
        }
    }

    private fun joinChannel(channelId: String = channelName) {
        if (engine == null)
            return
        if (joined)
            return
        /**In the demo, the default is to enter as the anchor. */
//        engine?.setClientRole(Constants.CLIENT_ROLE_AUDIENCE)
        /**Please configure accessToken in the string_config file.
         * A temporary token generated in Console. A temporary token is valid for 24 hours. For details, see
         * https://docs.agora.io/en/Agora%20Platform/token?platform=All%20Platforms#get-a-temporary-token
         * A token generated at the server. This applies to scenarios with high-security requirements. For details, see
         * https://docs.agora.io/en/cloud-recording/token_server_java?platform=Java */
//        accessToken = getString(R.string.agora_access_token)
        if (TextUtils.equals(accessToken, "") || TextUtils.equals(accessToken, "<#YOUR ACCESS TOKEN#>")) {
            accessToken = null
        }
        /** Allows a user to join a channel.
         * if you do not specify the uid, we will generate the uid for you */
        engine?.enableAudioVolumeIndication(1000, 3, true)
        val option = ChannelMediaOptions()
        option.autoSubscribeAudio = true
        val res = engine?.joinChannel(accessToken, channelId, myUid, option)
        if (res != 0) {
            // Usually happens with invalid parameters
            // Error code description can be found at:
            // en: https://docs.agora.io/en/Voice/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_engine_event_handler_1_1_error_code.html
            // cn: https://docs.agora.io/cn/Voice/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_engine_event_handler_1_1_error_code.html
            toast(RtcEngine.getErrorDescription(abs(res!!)))
            Log.e(TAG, RtcEngine.getErrorDescription(abs(res)))
            return
        }
        // Prevent repeated entry
    }


    override fun onRestart() {
        super.onRestart()
        /* if (kind != 1)
             mqttManager?.online()
         else {
             if (!isPhoneCall) {
                 mqttManager?.online()
             }
         }*/
        if (mqttManager != null) {
            mqttManager?.setOnReceivedDataListener(this)
        }
    }

    /** 判断麦克风是有效，有效返回true，否则返回false */
    fun validateMicAvailability() {
        var available = false
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return
        }
        val audioManager: AudioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
        val empty = audioManager.activeRecordingConfigurations.isEmpty()


        if (!empty) {
//                Timber.i("麦克风没有开始录制，说明被占用")
            val build: AlertDialog.Builder = AlertDialog.Builder(this)
            build.setMessage("麦克风已被占用")
            if (kind == 1 )
                mqttManager?.location("911")
            if (kind==2)
                mqttManager?.sendIp("911")
            build.setNegativeButton("确认", object : DialogInterface.OnClickListener {
                override fun onClick(dialog: DialogInterface?, which: Int) {
                    layout_login.visibility = VISIBLE
                    btn_quit.visibility = GONE
                    tv_local.visibility = INVISIBLE
                    tv_show_local.visibility = INVISIBLE
                    mqttManager?.offline()
                    mqttManager?.disconnect()
                    if (engine != null && joined)
                        engine?.leaveChannel()
                    engine = null
                    tv_phone_num.text = ""
                    stringBuffer = StringBuffer()
                    btn_del.visibility = GONE
                }
            }).create().show()
        }

    }

    override fun onDestroy() {
        super.onDestroy()
        disposable?.dispose()
        if (kind == 1 && isPhoneCalling) {
            hangUp(null)
        }
        if (engine != null && joined)
            engine?.leaveChannel()
        engine = null
        mqttManager?.offline()
        mqttManager?.disconnect()
        if (phoneReceiver != null)
            unregisterReceiver(phoneReceiver)
        Log.i("onDestroy", "onDestroy: ")
    }

    override fun onReceivedData(receiveBean: MqttMassgeSubscribBase) {
        Log.i("onReceivedData", "onReceivedData: $receiveBean")
        when (receiveBean.code) {
            EmqConstant.serverToAndroidEnum.offlie.code -> offline(receiveBean)
            EmqConstant.serverToAndroidEnum.occupy.code -> occupy()
            EmqConstant.serverToAndroidEnum.onLine.code -> online(receiveBean)
            EmqConstant.serverToAndroidEnum.hangUp.code -> hangUp(receiveBean)
            EmqConstant.serverToAndroidEnum.call.code -> call(receiveBean)
            EmqConstant.serverToAndroidEnum.ipAddress.code -> getIp(receiveBean)
            EmqConstant.serverToAndroidEnum.inCall.code -> inCall(receiveBean)
            EmqConstant.serverToAndroidEnum.answer.code -> answer(receiveBean)
            EmqConstant.serverToAndroidEnum.locationPhone.code -> locationPhone(receiveBean)

        }
    }

    private fun locationPhone(receiveBean: MqttMassgeSubscribBase) {
//        if (receiveBean.data?.location?.equals("000000")!!) {
//            tv_sim_num.text = "获取失败"
//            tv_local.text = "未知归属地"
//            return
//        } else
        if (receiveBean.data?.location?.equals("noSim")!!) {
            tv_sim_num.text = "无SIM服务"
            tv_sim_num.setBackgroundResource(R.drawable.bg_state_offline)
            tv_local.text = ""
            btn_call.setBackgroundResource(R.drawable.call_unable)
            btn_call.isEnabled = false
            return
        } else {
            tv_sim_num.text = ""

            btn_call.setBackgroundResource(R.drawable.call)
            btn_call.isEnabled = true
        }
        if (receiveBean.data?.location?.equals("911")!!) {
            val build: AlertDialog.Builder = AlertDialog.Builder(this)
            var create :AlertDialog? = null
            if (receiveBean.data?.fromSn?.contains("SIM") == true)
                build.setMessage("插卡端麦克风已被占用")
            else if (receiveBean.data?.fromSn?.contains("VOI") == true)
                build.setMessage("语音端麦克风已被占用")
            build.setNegativeButton("确认", object : DialogInterface.OnClickListener {
                override fun onClick(dialog: DialogInterface?, which: Int) {
                   create?.dismiss()
                }
            })
            create = build.create()
            create?.show()
        }
//            else{
//            val split = receiveBean.data?.location?.split("|")
//            if (split!=null&&split?.size==2){
//                tv_sim_num.text = split[1]
//                tv_local.text = split[0]
//            }
//        }
//        tv_local.text = receiveBean.data?.location
//        tv_show_local.visibility = VISIBLE
//        tv_local.visibility = VISIBLE
    }

    fun answer(receiveBean: MqttMassgeSubscribBase) {
        if (kind == 1) {
            onCallListener?.onAnswer()
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && Build.BRAND.toLowerCase().contains("oppo")) {
                acceptCall()
            }
        }
    }

    fun acceptCall() {
        val phoneManager: TelecomManager = getSystemService(Context.TELECOM_SERVICE) as TelecomManager
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ANSWER_PHONE_CALLS) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return
        }
        phoneManager.acceptRingingCall()
    }

    private fun inCall(receiveBean: MqttMassgeSubscribBase) {
        if (kind == 0) {
            if (loadingDialog == null)
                createLoadingDialog()
            loadingDialog?.setOutCall(false)
            loadingDialog?.setPhone(receiveBean.data?.phone)
            loadingDialog?.show()
        }
    }

    fun showCardCallIng(s: Boolean) {
        if (kind != 1)
            return
        runOnUiThread {
            if (s)
                tv_card_state.text = "状态\n呼叫中"
            else
                tv_card_state.text = "状态\n空闲"

        }
    }

    override fun onMqConnect() {
        if (isPhoneCalling) {
            mqttManager?.occupy()
            showCardCallIng(true)
        } else {
            mqttManager?.online()
        }
        ll_loading.visibility = GONE
        val info = StringBuffer()
        val fields: Array<Field> = Build::class.java.declaredFields
        for (field: Field in fields) {
            try {
                field.isAccessible = true
                if (field.name.equals("BRAND") || field.name.equals("MODEL"))
                    info.append(field.get(null)?.toString())
                Log.d(CrashHandler.TAG, field.name + " : " + field.get(null))
            } catch (e: Exception) {
                Log.e(CrashHandler.TAG, "an error occured when collect crash info", e)
            }
        }
        mqttManager?.deviceData("${Build.VERSION.SDK_INT}", info.toString())
        if (kind != 1)
//            initializeChannel()
        else {


            getLocal()


        }
//        validateMicAvailability()
    }

    override fun onError() {
        connectNet(false, "连接中断，正在重试")
    }


    private fun getLocal() {

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_NUMBERS) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {

            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return
        }
        val tm = getSystemService(TELEPHONY_SERVICE) as TelephonyManager //或者tel = TelephonyManager.from(mContext);
        val simState1 = tm.getSimState()
        if (simState1 != TelephonyManager.SIM_STATE_READY) {
            mqttManager?.location("noSim")
            return
        }
        /* val subscriptionManager: SubscriptionManager = SubscriptionManager.from(this)
         val activeSubscriptionInfoCount = subscriptionManager.activeSubscriptionInfoCount
         val simCardCount = Util.getSimCardCount(this)
         var count = 0
         for ( i in 0..simCardCount){
             val activeSubscriptionInfo = subscriptionManager.getActiveSubscriptionInfo(i)
             if (activeSubscriptionInfo!=null)
                 count++
         }
         if (activeSubscriptionInfoCount == 2||count==2) {
             AlertDialog.Builder(this).setNegativeButton("退出") { _, _ ->
                 layout_login.visibility = VISIBLE
                 btn_quit.visibility = GONE
                 mqttManager?.offline()
                 mqttManager?.disconnect()
 //                finish()

             }.setMessage("请勿同时启用插两张sim卡").setCancelable(false).create().show()

             return
         }
         */
        /* val line1Number = tm.line1Number
         val imei = tm.simSerialNumber
         var imsi: String? = tm.subscriberId
         //手机号码
         if (TextUtils.isEmpty(line1Number)) {
             mqttManager?.location("000000")
         } else
             thread {
                 if (!TextUtils.isEmpty(line1Number))
                     parsePhone(line1Number)
 //            parsePhone("13794923278")
             }*/
    }

    //手机号码归属地查询
    @kotlin.jvm.Throws(IOException::class, JSONException::class)
    fun parsePhone(phoneNumber: String?) {
        var result: String? = null
        val url = "http://apis.juhe.cn/mobile/get" //请求接口地址
        val params = HashMap<String?, String?>() //请求参数
        params["phone"] = phoneNumber //需要查询的手机号或手机号前7位
        params["key"] = "a77601ed6e5d3134e4e3aa406a193f6d" //应用APPKEY（应用详细页查询）
        params["dtype"] = "" //返回的数据格式，xml或者json，默认json
        //获取查询所返回的结果
        result = queryPhonePlace(url, params, "GET")
        val `object` = JSONObject(result)
        if (`object`.getInt("error_code") == 0) {
            val s: StringBuffer = StringBuffer()
            val object1 = `object`.getJSONObject("result")
            if (object1.has("province")) {
                s.append(object1.get("province"))
            }
            if (object1.has("city")) {
                s.append(object1.get("city"))
            }
            if (object1.has("company")) {
                s.append(object1.get("company"))
            }
            if (!TextUtils.isEmpty(
                            s.toString()
                    ))
                mqttManager?.location(s.toString() + "|" + phoneNumber)
        } else {
            Log.e("ActivityPhonePlace", "parsePhone: error_code" + `object`["error_code"] + ":" + `object`["reason"])
        }
    }

    /**
     * 获取网络资源，通过接口地址获取手机号码归属地
     * @param strUrl    请求接口地址
     * @param params    请求参数
     * @param method    请求方式
     * @return  查询到的结果，以Json形式返回
     * @throws IOException
     */
    @kotlin.jvm.Throws(IOException::class)
    fun queryPhonePlace(strUrl: String, params: Map<String?, String?>?, method: String?): String? {
        var strUrl = strUrl
        var conn: HttpURLConnection? = null
        var reader: BufferedReader? = null
        var rs: String? = null
        try {
            val sb = StringBuffer()
            if (method == null || method == "GET") {
                strUrl = strUrl + "?" + urlencode(params)
            }
            val url = URL(strUrl)
            conn = url.openConnection() as HttpURLConnection //打开和URL之间的连接
            //设置请求方式
            if (method == null || method == "GET") {
                conn.requestMethod = "GET"
            } else {
                conn.requestMethod = "POST"
                conn.doOutput = true
            }
            //设置通用请求属性
            conn.setRequestProperty("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36")
            conn.useCaches = false
            conn.connectTimeout = 30000
            conn.readTimeout = 30000
            conn.instanceFollowRedirects = false
            //建立实际的连接
            conn.connect()
            if (params != null && method == "POST") {
                try {
                    val out = DataOutputStream(conn.outputStream)
                    out.writeBytes(urlencode(params as Map<String?, String?>?))
                } catch (e: java.lang.Exception) {
                    // TODO: handle exception
                    e.printStackTrace()
                }
            }
            val `is` = conn.inputStream
            //定义BufferedReader输入流来读取URL的响应
            reader = BufferedReader(InputStreamReader(`is`, "UTF-8"))
            var strRead: String? = null
            while (reader.readLine().also { strRead = it } != null) {
                sb.append(strRead)
            }
            rs = sb.toString()
        } catch (e: UnsupportedEncodingException) {
            e.printStackTrace()
        } catch (e: ProtocolException) {
            e.printStackTrace()
        } catch (e: MalformedURLException) {
            e.printStackTrace()
        } catch (e: IOException) {
            e.printStackTrace()
        } //使用finally块来关闭输入流和连接
        finally {
            reader?.close()
            conn?.disconnect()
        }
        return rs
    }

    //将map类型转为请求参数类型
    @kotlin.jvm.Throws(UnsupportedEncodingException::class)
    fun urlencode(data: Map<String?, String?>?): String {
        val sb = StringBuilder()
        for (e: Map.Entry<*, *> in data!!) {
            sb.append(e.key).append("=").append(URLEncoder.encode(e.value.toString() + "", "UTF-8")).append("&")
        }
        return sb.toString()
    }

    var phoneReceiver: PhoneReceiver? = null
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == 666) {
            if (resultCode != RESULT_OK) {
                toast("配置默认电话失败")
                finish()
            }
        }
        if (requestCode == 555) {
            if (isDefaultPhoneCallApp()) {
                Log.i(TAG, "default")
            } else {
                Log.i(TAG, "not default")
            }
            if (Build.BRAND.toLowerCase().contains("oppo") && phoneReceiver == null) {
                phoneReceiver = PhoneReceiver()
                val filter = IntentFilter("android.intent.action.PHONE_STATE")
                filter.addAction("android.intent.action.NEW_OUTGOING_CALL")
                registerReceiver(phoneReceiver, filter)


                (getSystemService(TELEPHONY_SERVICE) as TelephonyManager).listen(object : PhoneStateListener() {
                    override fun onCallStateChanged(state: Int, phoneNumber: String) {
                        super.onCallStateChanged(state, phoneNumber)
                        when (state) {
                            TelephonyManager.CALL_STATE_RINGING -> mqttManager?.callIn(phoneNumber)
                            TelephonyManager.CALL_STATE_OFFHOOK -> {
                                mqttManager?.occupy()
                                showCardCallIng(true)
                            }
                            TelephonyManager.CALL_STATE_IDLE -> {}
                            else -> {}
                        }
                    }
                }, PhoneStateListener.LISTEN_CALL_STATE)
            }
        }
    }

    //判断是否是默认电话的应用
    fun isDefaultPhoneCallApp(): Boolean {
        val manger = getSystemService(Context.TELECOM_SERVICE) as? TelecomManager
        if (manger != null && manger.defaultDialerPackage != null) {
            return manger.defaultDialerPackage == packageName
        }
        return false
    }

    private fun getIp(receiveBean: MqttMassgeSubscribBase) {
        remoteIp = receiveBean.data?.ipAddress.toString()
        if (receiveBean.data?.ipAddress?.equals("911")!!) {
            val build: AlertDialog.Builder = AlertDialog.Builder(this)
            var create :AlertDialog? = null
            if (receiveBean.data?.fromSn?.contains("SIM") == true)
                build.setMessage("插卡端麦克风已被占用")
            else if (receiveBean.data?.fromSn?.contains("VOI") == true)
                build.setMessage("语音端麦克风已被占用")
            build.setNegativeButton("确认", object : DialogInterface.OnClickListener {
                override fun onClick(dialog: DialogInterface?, which: Int) {
                    create?.dismiss()
                }
            })
            create = build.create()
            create?.show()
        }

    }

    private fun offline(receiveBean: MqttMassgeSubscribBase) {
        if ("updPwd" == receiveBean.data?.action) {
            layout_login.visibility = VISIBLE
            btn_quit.visibility = GONE
            mqttManager?.offline()
            mqttManager?.disconnect()
            tv_local.visibility = INVISIBLE
            tv_show_local.visibility = INVISIBLE
            isRecording = false

            if (engine != null) {
                if (joined)
                    engine?.leaveChannel()
                engine = null
            }
            return
        }
        when {
            receiveBean.data?.fromSn?.contains("SIM") == true -> {
                simState = 0
                if (kind == 0 && loadingDialog != null) {
                    toastLong("插卡端已离线，请检查SIM卡是否支持边打电话边上网，建议在wifi环境下使用")

                }
            }
            receiveBean.data?.fromSn?.contains("VOI") == true -> {
                voiState = 0
            }
            receiveBean.data?.fromSn?.contains("CON") == true -> {
                conState = 0
            }
        }
        changeState()
    }

    private fun occupy() {
        if (kind != 0) {
            return
        }
        simState = 2
        changeState()
    }

    private fun online(receiveBean: MqttMassgeSubscribBase) {
        Log.i("online", "onReceived: $receiveBean")

        when {
            receiveBean.data?.fromSn?.contains("SIM") == true -> {
                simState = 1
                if (kind == 0 && loadingDialog != null) {
                    toast("插卡端通话已挂断")
                    loadingDialog?.online()
                }
            }
            receiveBean.data?.fromSn?.contains("VOI") == true -> {
                voiState = 1
                /*if (kind == 0) {
                    joinChannel(channelName)
                }*/
            }
            receiveBean.data?.fromSn?.contains("CON") == true -> {
                conState = 1
                if (kind == 1)
                    getLocal()
                /*if (kind == 2) {
                    joinChannel(channelName)
                }*/
            }
        }
        changeState()

    }

    fun hangUp(receiveBean: MqttMassgeSubscribBase?) {
        if (kind != 1) {
            return
        }
//        btn_hangup_out_call.performClick()
//        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && Build.BRAND.toLowerCase().contains("oppo")) {
        killPhoneCall()
        mqttManager?.online()
        showCardCallIng(false)
//        }
        onCallListener?.onHangup()
    }

    override fun onResume() {
        super.onResume()
        powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
        newWakeLock = powerManager?.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
                or PowerManager.ON_AFTER_RELEASE, Companion::class.java.toString())
        newWakeLock?.acquire(1000 * 60 * 1000L /*10 minutes*/)
    }

    override fun onPause() {
        super.onPause()
        newWakeLock?.release()

    }

    private var powerManager: PowerManager? = null
    private var newWakeLock: PowerManager.WakeLock? = null
    fun call(receiveBean: MqttMassgeSubscribBase) {
        if (kind != 1) {
            return
        }

        /*  powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
          newWakeLock = powerManager?.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Companion::class.java.toString())
          newWakeLock?.setReferenceCounted(false)
          newWakeLock?.acquire(30000)*/
//        newWakeLock.release()
        val intent = Intent(Intent.ACTION_CALL)
        intent.data = Uri.parse("tel:${receiveBean.data?.phone}")
        startActivity(intent)


        /*PhoneActivity.show(this,receiveBean.data?.phone,object :PhoneActivity.OnCallChangeListener{
            override fun onAnswer() {

            }

            override fun onHangup() {

            }
        },1)*/
    }


    private var stringBuffer = StringBuffer()
    fun onClick(view: View) {
        when (view.id) {
            R.id.btn_0 -> inputNum("0")
            R.id.btn_1 -> inputNum("1")
            R.id.btn_2 -> inputNum("2")
            R.id.btn_3 -> inputNum("3")
            R.id.btn_4 -> inputNum("4")
            R.id.btn_5 -> inputNum("5")
            R.id.btn_6 -> inputNum("6")
            R.id.btn_7 -> inputNum("7")
            R.id.btn_8 -> inputNum("8")
            R.id.btn_9 -> inputNum("9")
            R.id.btn_jin -> inputNum("#")
            R.id.btn_star -> inputNum("*")
            R.id.btn_del -> backspace()
            R.id.btn_hangup -> {
                mqttManager?.hangup(ouCallNum)
            }
            R.id.btn_quit -> {
//                val i=  1/0

                if (dialog == null)
                    dialog = AlertDialog.Builder(this).setNegativeButton("退出") { _, _ ->
                        layout_login.visibility = VISIBLE
                        btn_quit.visibility = GONE
                        tv_local.visibility = INVISIBLE
                        tv_show_local.visibility = INVISIBLE
                        mqttManager?.offline()
                        mqttManager?.disconnect()
                        if (engine != null && joined)
                            engine?.leaveChannel()
                        engine = null
                        tv_phone_num.text = ""
                        stringBuffer = StringBuffer()
                        btn_del.visibility = GONE
                    }.setPositiveButton("取消") { dialog, _ -> dialog?.dismiss() }.setMessage("退出当前账户？").create()
                dialog?.show()
            }
            R.id.img_show_hide -> {
                when (view.tag) {
                    "hide" -> {
                        view.tag = "show"
                        et_pass.inputType = InputType.TYPE_CLASS_NUMBER
                        img_show_hide.setImageResource(R.drawable.icon_show)
                    }
                    "show" -> {
                        view.tag = "hide"
                        et_pass.inputType = 0x00000012
                        img_show_hide.setImageResource(R.drawable.icon_hide)
                    }
                }
            }
        }
    }

    private fun inputNum(i: String) {
        if (stringBuffer.isEmpty())
            btn_del.visibility = VISIBLE
        stringBuffer.append(i)
        tv_phone_num.text = stringBuffer
    }

    private fun backspace() {
        if (stringBuffer.isNotEmpty())
            stringBuffer.deleteCharAt(stringBuffer.length - 1)
        tv_phone_num.text = stringBuffer
        if (stringBuffer.isEmpty())
            btn_del.visibility = GONE
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KEYCODE_BACK) {
            val intent = Intent(Intent.ACTION_MAIN)
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            intent.addCategory(Intent.CATEGORY_HOME)
            startActivity(intent)
            return true
        }
        return super.onKeyDown(keyCode, event)
    }

    private fun changeState() {
        when (conState) {
            0 -> {
                if (kind != 0) {

                    tv_con.text = "离线"
                    if (kind == 2) {

                        engine?.leaveChannel()

                        engine = null
                    }
                }
            }
            1 -> {
                if (kind != 0) {

                    tv_con.text = "在线"
                    if (kind == 2)
                        getTokenAndKey()
                }
            }

        }
        when (simState) {
            0 -> {
                tv_left.text = "离线"
                tv_left.setBackgroundResource(R.drawable.bg_state_offline)
                btn_call.setBackgroundResource(R.drawable.call_unable)
//                btn_hangup.visibility = GONE
                btn_call.isEnabled = false
            }
            1 -> {
                tv_left.text = "在线"
                tv_left.setBackgroundResource(R.drawable.bg_state_online)
                btn_call.setBackgroundResource(R.drawable.call)
//                btn_hangup.visibility = GONE
                btn_call.isEnabled = true

            }
            2 -> {
                tv_left.setBackgroundResource(R.drawable.bg_state_call)
                tv_left.text = "占线"
//                btn_hangup.visibility = VISIBLE
                if (loadingDialog != null) {
                    loadingDialog?.onTalking()
                }
            }
        }
        when (voiState) {
            0 -> {
                tv_right.text = "离线"
                tv_right.setBackgroundResource(R.drawable.bg_state_offline)
                if (kind == 0) {
                    engine?.leaveChannel()
                    engine = null
                }
            }
            1 -> {
                if (kind == 0)
                    getTokenAndKey()
                tv_right.setBackgroundResource(R.drawable.bg_state_online)

                tv_right.text = "在线"
            }
        }
    }

    private var isPhoneCalling: Boolean = false
    private var onCallListener: PhoneActivity.OnCallChangeListener? = null
    fun onPhoneOutCall(phoneNumber: String?, onCallChangeListener: PhoneActivity.OnCallChangeListener, callType: CallType) {
        isPhoneCalling = true
        showCardCallIng(true)
        onCallListener = onCallChangeListener
        if (callType == CallType.CALL_IN)
            mqttManager?.callIn(phoneNumber)
//        tv_phone_num_out_call.text = phoneNumber
        /* btn_hangup_out_call.visibility = View.VISIBLE
         btn_hangup_out_call.setOnClickListener(object : OnClickListener {
             override fun onClick(v: View?) {
                 onCallChangeListener.onHangup()
             }
         })*/
    }

    @SuppressLint("Range")
    fun onHandupOutCall() {
//        tv_phone_num_out_call.text = ""
//        btn_hangup_out_call.visibility = View.GONE
        isPhoneCalling = false
        showCardCallIng(false)
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_CALL_LOG) != PackageManager.PERMISSION_GRANTED)
            return
        val resolver = contentResolver
//        val cursor = resolver.query(CallLog.Calls.CONTENT_URI, null, null, null)
//        while (cursor?.moveToNext() == true) {
//            val string = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID))
//
//            resolver.delete(CallLog.Calls.CONTENT_URI, "number=?", arrayOf(phoneNumber))
//
//        }
        resolver.delete(CallLog.Calls.CONTENT_URI, null, null)

    }

    fun connectNet(b: Boolean, s: String = "网络故障,等待网络重连...") {

        runOnUiThread() {
            when (b) {
                true -> {
                    ll_loading.visibility = GONE
                    tv_loading_info.text = "加载中..."
                }
                false -> {
                    ll_loading.visibility = VISIBLE
                    tv_loading_info.text = s
                }
            }
        }

        if (kind
                == 1 && b) {
            getLocal()
        }
    }

    private fun killPhoneCall(): Boolean {
        try {
            tryEndCall()
            val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
            val classTelephony = Class.forName(telephonyManager.javaClass.name)
            val methodGetITelephony = classTelephony.getDeclaredMethod("getITelephony")
            methodGetITelephony.isAccessible = true
            val telephonyInterface = methodGetITelephony.invoke(telephonyManager)
            val telephonyInterfaceClass = Class.forName(telephonyInterface.javaClass.name)
            val methodEndCall = telephonyInterfaceClass.getDeclaredMethod("endCall")
            methodEndCall.invoke(telephonyInterface)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            Log.d("TAG1", "hangupPhoneCall: $e")
            return false
        }
        return true
    }

    private fun tryEndCall() {
        try {
            val telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager
            val res = telecomManager.endCall()
            Log.d("TAG1", "tryEndCall: $res")
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
    }

}
